home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / gpt32src.zip / MISC.C < prev    next >
C/C++ Source or Header  |  1992-03-25  |  23KB  |  879 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: misc.c,v 3.26 92/03/24 22:34:30 woo Exp Locker: woo $";
  3. #endif
  4.  
  5. /* GNUPLOT - misc.c */
  6. /*
  7.  * Copyright (C) 1986, 1987, 1990, 1991, 1992   Thomas Williams, Colin Kelley
  8.  *
  9.  * Permission to use, copy, and distribute this software and its
  10.  * documentation for any purpose with or without fee is hereby granted, 
  11.  * provided that the above copyright notice appear in all copies and 
  12.  * that both that copyright notice and this permission notice appear 
  13.  * in supporting documentation.
  14.  *
  15.  * Permission to modify the software is granted, but not the right to
  16.  * distribute the modified code.  Modifications are to be distributed 
  17.  * as patches to released version.
  18.  *  
  19.  * This software is provided "as is" without express or implied warranty.
  20.  * 
  21.  *
  22.  * AUTHORS
  23.  * 
  24.  *   Original Software:
  25.  *     Thomas Williams,  Colin Kelley.
  26.  * 
  27.  *   Gnuplot 2.0 additions:
  28.  *       Russell Lang, Dave Kotz, John Campbell.
  29.  *
  30.  *   Gnuplot 3.0 additions:
  31.  *       Gershon Elber and many others.
  32.  * 
  33.  * Send your comments or suggestions to 
  34.  *  info-gnuplot@ames.arc.nasa.gov.
  35.  * This is a mailing list; to join it send a note to 
  36.  *  info-gnuplot-request@ames.arc.nasa.gov.  
  37.  * Send bug reports to
  38.  *  bug-gnuplot@ames.arc.nasa.gov.
  39.  */
  40.  
  41. #include <stdio.h>
  42. #include <math.h>
  43. #include "plot.h"
  44. #include "setshow.h"
  45. #include "help.h"
  46. #ifdef __TURBOC__
  47. #include <graphics.h>
  48. #endif
  49.  
  50. #ifndef _IBMR2
  51. extern char *malloc();
  52. extern char *realloc();
  53. #endif
  54.  
  55. extern int c_token;
  56. extern char replot_line[];
  57. extern struct at_type at;
  58. extern struct ft_entry ft[];
  59. extern struct udft_entry *first_udf;
  60. extern struct udvt_entry *first_udv;
  61.  
  62. extern struct at_type *temp_at();
  63.  
  64. extern BOOLEAN interactive;
  65. extern char *infile_name;
  66. extern int inline_num;
  67.  
  68. /* State information for load_file(), to recover from errors
  69.  * and properly handle recursive load_file calls
  70.  */
  71. typedef struct lf_state_struct LFS;
  72. struct lf_state_struct {
  73.     FILE *fp;                /* file pointer for load file */
  74.     char *name;            /* name of file */
  75.     BOOLEAN interactive;        /* value of interactive flag on entry */
  76.     int inline_num;            /* inline_num on entry */
  77.     LFS *prev;                /* defines a stack */
  78. } *lf_head = NULL;            /* NULL if not in load_file */
  79.  
  80. static BOOLEAN lf_pop();
  81. static void lf_push();
  82.  
  83. /*
  84.  * instead of <strings.h>
  85.  */
  86. extern int strcmp();
  87.  
  88. /*
  89.  * Turbo C realloc does not do the right thing. Here is what it should do.
  90.  */
  91. #ifdef __TURBOC__
  92. char *realloc(p, new_size)
  93.           void *p;
  94.           size_t new_size;
  95. {
  96.     void *new_p = alloc(new_size, "TC realloc");
  97.  
  98.     /* Note p may have less than new_size bytes but in this unprotected
  99.      * environment this will work.
  100.      */
  101.     memcpy(new_p, p, new_size);
  102.     free(p);
  103.     return new_p;
  104. }
  105. #endif /* __TURBOC__ */
  106.  
  107. /*
  108.  * cp_alloc() allocates a curve_points structure that can hold 'num'
  109.  * points.
  110.  */
  111. struct curve_points *
  112. cp_alloc(num)
  113.     int num;
  114. {
  115.     struct curve_points *cp;
  116.     cp = (struct curve_points *) alloc(sizeof(struct curve_points), "curve");
  117.     cp->p_max = (num >= 0 ? num : 0);
  118.     if (num > 0) {
  119.        cp->points = (struct coordinate *)
  120.         alloc(num * sizeof(struct coordinate), "curve points");
  121.     } else
  122.        cp->points = (struct coordinate *) NULL;
  123.     cp->next_cp = NULL;
  124.     cp->title = NULL;
  125.     return(cp);
  126. }
  127.  
  128.  
  129. /*
  130.  * cp_extend() reallocates a curve_points structure to hold "num"
  131.  * points. This will either expand or shrink the storage.
  132.  */
  133. cp_extend(cp, num)
  134.     struct curve_points *cp;
  135.     int num;
  136. {
  137.     struct coordinate *new;
  138.  
  139. #ifdef PC
  140.     /* Make sure we do not allocate more than 64k (8088 architecture...)
  141.      * in msdos since we can not address more. Leave some bytes for malloc
  142.      * maintainance.
  143.      */
  144.     if (num > 65500L / sizeof(struct coordinate))
  145.     int_error("Can not allocate more than 64k in msdos", NO_CARET);
  146. #endif /* PC */
  147.  
  148.     if (num == cp->p_max) return;
  149.  
  150.     if (num > 0) {
  151.        if (cp->points == NULL) {
  152.           cp->points = (struct coordinate *)
  153.             alloc(num * sizeof(struct coordinate), "curve points");
  154.        } else {
  155.           new = (struct coordinate *)
  156.             realloc(cp->points, num * sizeof(struct coordinate));
  157.           if (new == (struct coordinate *) NULL) {
  158.              int_error("No memory available for expanding curve points",
  159.                      NO_CARET);
  160.              /* NOTREACHED */
  161.           }
  162.           cp->points = new;
  163.        }
  164.        cp->p_max = num;
  165.     } else {
  166.        if (cp->points != (struct coordinate *) NULL)
  167.         free(cp->points);
  168.        cp->points = (struct coordinate *) NULL;
  169.        cp->p_max = 0;
  170.     }
  171. }
  172.  
  173. /*
  174.  * cp_free() releases any memory which was previously malloc()'d to hold
  175.  *   curve points (and recursively down the linked list).
  176.  */
  177. cp_free(cp)
  178. struct curve_points *cp;
  179. {
  180.     if (cp) {
  181.         cp_free(cp->next_cp);
  182.         if (cp->title)
  183.             free((char *)cp->title);
  184.         if (cp->points)
  185.             free((char *)cp->points);
  186.         free((char *)cp);
  187.     }
  188. }
  189.  
  190. /*
  191.  * iso_alloc() allocates a iso_curve structure that can hold 'num'
  192.  * points.
  193.  */
  194. struct iso_curve *
  195. iso_alloc(num)
  196.     int num;
  197. {
  198.     struct iso_curve *ip;
  199.     ip = (struct iso_curve *) alloc(sizeof(struct iso_curve), "iso curve");
  200.     ip->p_max = (num >= 0 ? num : 0);
  201.     if (num > 0) {
  202.        ip->points = (struct coordinate *)
  203.         alloc(num * sizeof(struct coordinate), "iso curve points");
  204.     } else
  205.        ip->points = (struct coordinate *) NULL;
  206.     ip->next = NULL;
  207.     return(ip);
  208. }
  209.  
  210. /*
  211.  * iso_extend() reallocates a iso_curve structure to hold "num"
  212.  * points. This will either expand or shrink the storage.
  213.  */
  214. iso_extend(ip, num)
  215.     struct iso_curve *ip;
  216.     int num;
  217. {
  218.     struct coordinate *new;
  219.  
  220.     if (num == ip->p_max) return;
  221.  
  222. #ifdef PC
  223.     /* Make sure we do not allocate more than 64k (8088 architecture...)
  224.      * in msdos since we can not address more. Leave some bytes for malloc
  225.      * maintainance.
  226.      */
  227.     if (num > 65500L / sizeof(struct coordinate))
  228.     int_error("Can not allocate more than 64k in msdos", NO_CARET);
  229. #endif /* PC */
  230.  
  231.     if (num > 0) {
  232.        if (ip->points == NULL) {
  233.           ip->points = (struct coordinate *)
  234.             alloc(num * sizeof(struct coordinate), "iso curve points");
  235.        } else {
  236.           new = (struct coordinate *)
  237.             realloc(ip->points, num * sizeof(struct coordinate));
  238.           if (new == (struct coordinate *) NULL) {
  239.              int_error("No memory available for expanding curve points",
  240.                      NO_CARET);
  241.              /* NOTREACHED */
  242.           }
  243.           ip->points = new;
  244.        }
  245.        ip->p_max = num;
  246.     } else {
  247.        if (ip->points != (struct coordinate *) NULL)
  248.         free(ip->points);
  249.        ip->points = (struct coordinate *) NULL;
  250.        ip->p_max = 0;
  251.     }
  252. }
  253.  
  254. /*
  255.  * iso_free() releases any memory which was previously malloc()'d to hold
  256.  *   iso curve points.
  257.  */
  258. iso_free(ip)
  259. struct iso_curve *ip;
  260. {
  261.     if (ip) {
  262.         if (ip->points)
  263.             free((char *)ip->points);
  264.         free((char *)ip);
  265.     }
  266. }
  267.  
  268. /*
  269.  * sp_alloc() allocates a surface_points structure that can hold 'num_iso'
  270.  * iso-curves, each of which 'num_samp' samples.
  271.  * if, however num_iso or num_samp is zero no iso curves are allocated.
  272.  */
  273. struct surface_points *
  274. sp_alloc(num_samp,num_iso)
  275.     int num_samp,num_iso;
  276. {
  277.     struct surface_points *sp;
  278.  
  279.     sp = (struct surface_points *) alloc(sizeof(struct surface_points), "surface");
  280.     sp->next_sp = NULL;
  281.     sp->title = NULL;
  282.     sp->contours = NULL;
  283.     sp->iso_crvs = NULL;
  284.     sp->num_iso_read = 0;
  285.  
  286.     if (num_iso > 0 && num_samp > 0) {
  287.     int i;
  288.     struct iso_curve *icrv;
  289.  
  290.     for (i = 0; i < num_iso; i++) {
  291.         icrv = iso_alloc(num_samp);
  292.         icrv->next = sp->iso_crvs;
  293.         sp->iso_crvs = icrv;
  294.     }
  295.     } else
  296.     sp->iso_crvs = (struct iso_curve *) NULL;
  297.  
  298.     return(sp);
  299. }
  300.  
  301. /*
  302.  * sp_replace() updates a surface_points structure so it can hold 'num_iso'
  303.  * iso-curves, each of which 'num_samp' samples.
  304.  * if, however num_iso or num_samp is zero no iso curves are allocated.
  305.  */
  306. sp_replace(sp,num_samp,num_iso)
  307.        struct surface_points *sp;
  308.        int num_samp,num_iso;
  309. {
  310.     int i;
  311.     struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  312.  
  313.     while ( icrvs ) {
  314.     icrv = icrvs;
  315.     icrvs = icrvs->next;
  316.     iso_free( icrv );
  317.     }
  318.     sp->iso_crvs = NULL;
  319.     
  320.     if (num_iso > 0 && num_samp > 0) {
  321.     for (i = 0; i < num_iso; i++) {
  322.         icrv = iso_alloc(num_samp);
  323.         icrv->next = sp->iso_crvs;
  324.         sp->iso_crvs = icrv;
  325.     }
  326.     } else
  327.     sp->iso_crvs = (struct iso_curve *) NULL;
  328. }
  329.  
  330. /*
  331.  * sp_free() releases any memory which was previously malloc()'d to hold
  332.  *   surface points.
  333.  */
  334. sp_free(sp)
  335. struct surface_points *sp;
  336. {
  337.     if (sp) {
  338.         sp_free(sp->next_sp);
  339.         if (sp->title)
  340.             free((char *)sp->title);
  341.         if (sp->contours) {
  342.             struct gnuplot_contours *cntr, *cntrs = sp->contours;
  343.  
  344.             while (cntrs) {
  345.                 cntr = cntrs;
  346.                 cntrs = cntrs->next;
  347.                 free(cntr->coords);
  348.                 free(cntr);
  349.             }
  350.         }
  351.         if (sp->iso_crvs) {
  352.             struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  353.  
  354.             while (icrvs) {
  355.                 icrv = icrvs;
  356.                 icrvs = icrvs->next;
  357.                 iso_free(icrv);
  358.             }
  359.         }
  360.         free((char *)sp);
  361.     }
  362. }
  363.  
  364.  
  365.  
  366. save_functions(fp)
  367. FILE *fp;
  368. {
  369. register struct udft_entry *udf = first_udf;
  370.  
  371.     if (fp) {
  372.         while (udf) {
  373.             if (udf->definition)
  374.                 fprintf(fp,"%s\n",udf->definition);
  375.             udf = udf->next_udf;
  376.         }
  377.         (void) fclose(fp);
  378.     } else
  379.         os_error("Cannot open save file",c_token);            
  380. }
  381.  
  382.  
  383. save_variables(fp)
  384. FILE *fp;
  385. {
  386. register struct udvt_entry *udv = first_udv->next_udv;    /* skip pi */
  387.  
  388.     if (fp) {
  389.         while (udv) {
  390.             if (!udv->udv_undef) {
  391.                 fprintf(fp,"%s = ",udv->udv_name);
  392.                 disp_value(fp,&(udv->udv_value));
  393.                 (void) putc('\n',fp);
  394.             }
  395.             udv = udv->next_udv;
  396.         }
  397.         (void) fclose(fp);
  398.     } else
  399.         os_error("Cannot open save file",c_token);            
  400. }
  401.  
  402.  
  403. save_all(fp)
  404. FILE *fp;
  405. {
  406. register struct udft_entry *udf = first_udf;
  407. register struct udvt_entry *udv = first_udv->next_udv;    /* skip pi */
  408.  
  409.     if (fp) {
  410.         save_set_all(fp);
  411.         while (udf) {
  412.             if (udf->definition)
  413.                 fprintf(fp,"%s\n",udf->definition);
  414.             udf = udf->next_udf;
  415.         }
  416.         while (udv) {
  417.             if (!udv->udv_undef) {
  418.                 fprintf(fp,"%s = ",udv->udv_name);
  419.                 disp_value(fp,&(udv->udv_value));
  420.                 (void) putc('\n',fp);
  421.             }
  422.             udv = udv->next_udv;
  423.         }
  424.         fprintf(fp,"%s\n",replot_line);
  425.         (void) fclose(fp);
  426.     } else
  427.         os_error("Cannot open save file",c_token);            
  428. }
  429.  
  430.  
  431. save_set(fp)
  432. FILE *fp;
  433. {
  434.     if (fp) {
  435.         save_set_all(fp);
  436.         (void) fclose(fp);
  437.     } else
  438.         os_error("Cannot open save file",c_token);            
  439. }
  440.  
  441.  
  442. save_set_all(fp)
  443. FILE *fp;
  444. {
  445. struct text_label *this_label;
  446. struct arrow_def *this_arrow;
  447.     fprintf(fp,"set terminal %s %s\n", term_tbl[term].name, term_options);
  448.     fprintf(fp,"set output %s\n",strcmp(outstr,"STDOUT")? outstr : "" );
  449.     fprintf(fp,"set %sclip points\n", (clip_points)? "" : "no");
  450.     fprintf(fp,"set %sclip one\n", (clip_lines1)? "" : "no");
  451.     fprintf(fp,"set %sclip two\n", (clip_lines2)? "" : "no");
  452.     fprintf(fp,"set %sborder\n",draw_border ? "" : "no");
  453.     fprintf(fp,"set dummy %s,%s\n",dummy_var[0], dummy_var[1]);
  454.     fprintf(fp,"set format x \"%s\"\n", xformat);
  455.     fprintf(fp,"set format y \"%s\"\n", yformat);
  456.     fprintf(fp,"set format z \"%s\"\n", zformat);
  457.     fprintf(fp,"set %sgrid\n", (grid)? "" : "no");
  458.     switch (key) {
  459.         case -1 : 
  460.             fprintf(fp,"set key\n");
  461.             break;
  462.         case 0 :
  463.             fprintf(fp,"set nokey\n");
  464.             break;
  465.         case 1 :
  466.             fprintf(fp,"set key %g,%g,%g\n",key_x,key_y,key_z);
  467.             break;
  468.     }
  469.     fprintf(fp,"set nolabel\n");
  470.     for (this_label = first_label; this_label != NULL;
  471.             this_label = this_label->next) {
  472.         fprintf(fp,"set label %d \"%s\" at %g,%g,%g ",
  473.                this_label->tag,
  474.                this_label->text, this_label->x,
  475.                          this_label->y,
  476.                          this_label->z);
  477.         switch(this_label->pos) {
  478.             case LEFT : 
  479.                 fprintf(fp,"left");
  480.                 break;
  481.             case CENTRE :
  482.                 fprintf(fp,"centre");
  483.                 break;
  484.             case RIGHT :
  485.                 fprintf(fp,"right");
  486.                 break;
  487.         }
  488.         fputc('\n',fp);
  489.     }
  490.     fprintf(fp,"set noarrow\n");
  491.     for (this_arrow = first_arrow; this_arrow != NULL;
  492.             this_arrow = this_arrow->next) {
  493.         fprintf(fp,"set arrow %d from %g,%g,%g to %g,%g,%g%s\n",
  494.                this_arrow->tag,
  495.                this_arrow->sx, this_arrow->sy, this_arrow->sz,
  496.                this_arrow->ex, this_arrow->ey, this_arrow->ez,
  497.                this_arrow->head ? "" : " nohead");
  498.     }
  499.     fprintf(fp,"set nologscale\n");
  500.     if (log_x||log_y)
  501.         fprintf(fp,"set logscale %c%c\n", 
  502.         log_x ? 'x' : ' ', log_y ? 'y' : ' ');
  503.     if (log_z) fprintf(fp,"set logscale z\n");
  504.     fprintf(fp,"set offsets %g, %g, %g, %g\n",loff,roff,toff,boff);
  505.     fprintf(fp,"set %spolar\n", (polar)? "" : "no");
  506.     fprintf(fp,"set angles %s\n", (angles_format == ANGLES_RADIANS)?
  507.                         "radians" : "degrees");
  508.     fprintf(fp,"set %sparametric\n", (parametric)? "" : "no");
  509.     fprintf(fp,"set view %g, %g, %g, %g\n",
  510.         surface_rot_x, surface_rot_z, surface_scale, surface_zscale);
  511.     fprintf(fp,"set samples %d\n",samples);
  512.     fprintf(fp,"set isosamples %d\n",iso_samples);
  513.     fprintf(fp,"set %ssurface\n",(draw_surface) ? "" : "no");
  514.     fprintf(fp,"set %scontour",(draw_contour) ? "" : "no");
  515.     switch (draw_contour) {
  516.         case CONTOUR_NONE: fprintf(fp, "\n"); break;
  517.         case CONTOUR_BASE: fprintf(fp, " base\n"); break;
  518.         case CONTOUR_SRF:  fprintf(fp, " surface\n"); break;
  519.         case CONTOUR_BOTH: fprintf(fp, " both\n"); break;
  520.     }
  521.     fprintf(fp,"set %shidden3d\n",(hidden3d) ? "" : "no");
  522.     fprintf(fp,"set cntrparam order %d\n", contour_order);
  523.     fprintf(fp,"set cntrparam ");
  524.     switch (contour_kind) {
  525.         case CONTOUR_KIND_LINEAR:    fprintf(fp, "linear\n"); break;
  526.         case CONTOUR_KIND_CUBIC_SPL: fprintf(fp, "cubicspline\n"); break;
  527.         case CONTOUR_KIND_BSPLINE:   fprintf(fp, "bspline\n"); break;
  528.     }
  529.     fprintf(fp,"set cntrparam points %d\n", contour_pts);
  530.     fprintf(fp,"set size %g,%g\n",xsize,ysize);
  531.     fprintf(fp,"set data style ");
  532.     switch (data_style) {
  533.         case LINES: fprintf(fp,"lines\n"); break;
  534.         case POINTS: fprintf(fp,"points\n"); break;
  535.         case IMPULSES: fprintf(fp,"impulses\n"); break;
  536.         case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
  537.         case DOTS: fprintf(fp,"dots\n"); break;
  538.         case ERRORBARS: fprintf(fp,"errorbars\n"); break;
  539.     }
  540.     fprintf(fp,"set function style ");
  541.     switch (func_style) {
  542.         case LINES: fprintf(fp,"lines\n"); break;
  543.         case POINTS: fprintf(fp,"points\n"); break;
  544.         case IMPULSES: fprintf(fp,"impulses\n"); break;
  545.         case LINESPOINTS: fprintf(fp,"linespoints\n"); break;
  546.         case DOTS: fprintf(fp,"dots\n"); break;
  547.         case ERRORBARS: fprintf(fp,"errorbars\n"); break;
  548.     }
  549.     fprintf(fp,"set tics %s\n", (tic_in)? "in" : "out");
  550.     fprintf(fp,"set ticslevel %g\n", ticslevel);
  551.     save_tics(fp, xtics, 'x', &xticdef);
  552.     save_tics(fp, ytics, 'y', &yticdef);
  553.     save_tics(fp, ztics, 'z', &zticdef);
  554.     fprintf(fp,"set title \"%s\" %d,%d\n",title,title_xoffset,title_yoffset);
  555.         if (timedate)
  556.         fprintf(fp,"set time %d,%d\n",time_xoffset,time_yoffset);
  557.     else
  558.         fprintf(fp,"set notime\n");
  559.      fprintf(fp,"set rrange [%g : %g]\n",rmin,rmax);
  560.     fprintf(fp,"set trange [%g : %g]\n",tmin,tmax);
  561.     fprintf(fp,"set xlabel \"%s\" %d,%d\n",xlabel,xlabel_xoffset,xlabel_yoffset);
  562.     fprintf(fp,"set xrange [%g : %g]\n",xmin,xmax);
  563.     fprintf(fp,"set ylabel \"%s\" %d,%d\n",ylabel,ylabel_xoffset,ylabel_yoffset);
  564.     fprintf(fp,"set yrange [%g : %g]\n",ymin,ymax);
  565.     fprintf(fp,"set zlabel \"%s\" %d,%d\n",zlabel,zlabel_xoffset,zlabel_yoffset);
  566.     fprintf(fp,"set zrange [%g : %g]\n",zmin,zmax);
  567.     fprintf(fp,"set %s %c\n", 
  568.         autoscale_r ? "autoscale" : "noautoscale", 'r');
  569.     fprintf(fp,"set %s %c\n", 
  570.         autoscale_t ? "autoscale" : "noautoscale", 't');
  571.     fprintf(fp,"set %s %c%c\n", 
  572.         (autoscale_y||autoscale_x) ? "autoscale" : "noautoscale", 
  573.         autoscale_x ? 'x' : ' ', autoscale_y ? 'y' : ' ');
  574.     fprintf(fp,"set %s %c\n", 
  575.         autoscale_z ? "autoscale" : "noautoscale", 'z');
  576.     fprintf(fp,"set zero %g\n",zero);
  577. }
  578.  
  579. save_tics(fp, onoff, axis, tdef)
  580.     FILE *fp;
  581.     BOOLEAN onoff;
  582.     char axis;
  583.     struct ticdef *tdef;
  584. {
  585.     if (onoff) {
  586.        fprintf(fp,"set %ctics", axis);
  587.        switch(tdef->type) {
  588.           case TIC_COMPUTED: {
  589.              break;
  590.           }
  591.           case TIC_SERIES: {
  592.                  if (tdef->def.series.end >= VERYLARGE)
  593.                  fprintf(fp, " %g,%g", tdef->def.series.start,
  594.                                         tdef->def.series.incr);
  595.                          else
  596.                  fprintf(fp, " %g,%g,%g", tdef->def.series.start,
  597.                                         tdef->def.series.incr, tdef->def.series.end);
  598.              break;
  599.           }
  600.           case TIC_USER: {
  601.              register struct ticmark *t;
  602.              fprintf(fp, " (");
  603.              for (t = tdef->def.user; t != NULL; t=t->next) {
  604.                 if (t->label)
  605.                   fprintf(fp, "\"%s\" ", t->label);
  606.                 if (t->next)
  607.                   fprintf(fp, "%g, ", t->position);
  608.                 else
  609.                   fprintf(fp, "%g", t->position);
  610.              }
  611.              fprintf(fp, ")");
  612.              break;
  613.           } 
  614.        }
  615.        fprintf(fp, "\n");
  616.     } else {
  617.        fprintf(fp,"set no%ctics\n", axis);
  618.     }
  619. }
  620.  
  621. load_file(fp, name)
  622.     FILE *fp;
  623.     char *name;
  624. {
  625.     register int len;
  626.     extern char input_line[];
  627.  
  628.     int start, left;
  629.     int more;
  630.     int stop = FALSE;
  631.  
  632.     lf_push(fp);            /* save state for errors and recursion */
  633.  
  634.     if (fp == (FILE *)NULL) {
  635.        char errbuf[BUFSIZ];
  636.        (void) sprintf(errbuf, "Cannot open load file '%s'", name);
  637.        os_error(errbuf, c_token);
  638.     } else {
  639.        /* go into non-interactive mode during load */
  640.        /* will be undone below, or in load_file_error */
  641.        interactive = FALSE;
  642.        inline_num = 0;
  643.        infile_name = name;
  644.  
  645.        while (!stop) {        /* read all commands in file */
  646.           /* read one command */
  647.           left = MAX_LINE_LEN;
  648.           start = 0;
  649.           more = TRUE;
  650.  
  651.           while (more) {
  652.              if (fgets(&(input_line[start]), left, fp) == NULL) {
  653.                 stop = TRUE; /* EOF in file */
  654.                 input_line[start] = '\0';
  655.                 more = FALSE;    
  656.              } else {
  657.                 inline_num++;
  658.                 len = strlen(input_line) - 1;
  659.                 if (input_line[len] == '\n') { /* remove any newline */
  660.                     input_line[len] = '\0';
  661.                     /* Look, len was 1-1 = 0 before, take care here! */
  662.                     if (len > 0) --len;
  663.                 } else if (len+1 >= left)
  664.                   int_error("Input line too long",NO_CARET);
  665.                  
  666.                 if (input_line[len] == '\\') { /* line continuation */
  667.                     start = len;
  668.                     left  = MAX_LINE_LEN - start; /* left -=len;*/
  669.                 } else
  670.                   more = FALSE;
  671.              }
  672.           }
  673.  
  674.           if (strlen(input_line) > 0) {
  675.              screen_ok = FALSE;    /* make sure command line is
  676.                                echoed on error */
  677.              do_line();
  678.           }
  679.        }
  680.     }
  681.  
  682.     /* pop state */
  683.     (void) lf_pop();        /* also closes file fp */
  684. }
  685.  
  686. /* pop from load_file state stack */
  687. static BOOLEAN                /* FALSE if stack was empty */
  688. lf_pop()                    /* called by load_file and load_file_error */
  689. {
  690.     LFS *lf;
  691.  
  692.     if (lf_head == NULL)
  693.      return(FALSE);
  694.     else {
  695.        lf = lf_head;
  696.        if (lf->fp != (FILE *)NULL)
  697.         (void) fclose(lf->fp);
  698.        interactive = lf->interactive;
  699.        inline_num = lf->inline_num;
  700.        infile_name = lf->name;
  701.        lf_head = lf->prev;
  702.        free((char *)lf);
  703.        return(TRUE);
  704.     }
  705. }
  706.  
  707. /* push onto load_file state stack */
  708. /* essentially, we save information needed to undo the load_file changes */
  709. static void
  710. lf_push(fp)            /* called by load_file */
  711.     FILE *fp;
  712. {
  713.     LFS *lf;
  714.     
  715.     lf = (LFS *)alloc(sizeof(LFS), (char *)NULL);
  716.     if (lf == (LFS *)NULL) {
  717.        if (fp != (FILE *)NULL)
  718.         (void) fclose(fp);        /* it won't be otherwise */
  719.        int_error("not enough memory to load file", c_token);
  720.     }
  721.      
  722.     lf->fp = fp;            /* save this file pointer */
  723.     lf->name = infile_name;    /* save current name */
  724.     lf->interactive = interactive;    /* save current state */
  725.     lf->inline_num = inline_num; /* save current line number */
  726.     lf->prev = lf_head;        /* link to stack */
  727.     lf_head = lf;
  728. }
  729.  
  730. load_file_error()            /* called from main */
  731. {
  732.     /* clean up from error in load_file */
  733.     /* pop off everything on stack */
  734.     while(lf_pop())
  735.      ;
  736. }
  737.  
  738. /* find char c in string str; return p such that str[p]==c;
  739.  * if c not in str then p=strlen(str)
  740.  */
  741. int
  742. instring(str, c)
  743.     char *str;
  744.     char c;
  745. {
  746.     int pos = 0;
  747.  
  748.     while (str != NULL && *str != '\0' && c != *str) {
  749.        str++; 
  750.        pos++;
  751.     }
  752.     return (pos);
  753. }
  754.  
  755. show_functions()
  756. {
  757. register struct udft_entry *udf = first_udf;
  758.  
  759.     fprintf(stderr,"\n\tUser-Defined Functions:\n");
  760.  
  761.     while (udf) {
  762.         if (udf->definition)
  763.             fprintf(stderr,"\t%s\n",udf->definition);
  764.         else
  765.             fprintf(stderr,"\t%s is undefined\n",udf->udf_name);
  766.         udf = udf->next_udf;
  767.     }
  768. }
  769.  
  770.  
  771. show_at()
  772. {
  773.     (void) putc('\n',stderr);
  774.     disp_at(temp_at(),0);
  775. }
  776.  
  777.  
  778. disp_at(curr_at, level)
  779. struct at_type *curr_at;
  780. int level;
  781. {
  782. register int i, j;
  783. register union argument *arg;
  784.  
  785.     for (i = 0; i < curr_at->a_count; i++) {
  786.         (void) putc('\t',stderr);
  787.         for (j = 0; j < level; j++)
  788.             (void) putc(' ',stderr);    /* indent */
  789.  
  790.             /* print name of instruction */
  791.  
  792.         fputs(ft[(int)(curr_at->actions[i].index)].f_name,stderr);
  793.         arg = &(curr_at->actions[i].arg);
  794.  
  795.             /* now print optional argument */
  796.  
  797.         switch(curr_at->actions[i].index) {
  798.           case PUSH:    fprintf(stderr," %s\n", arg->udv_arg->udv_name);
  799.                     break;
  800.           case PUSHC:    (void) putc(' ',stderr);
  801.                     disp_value(stderr,&(arg->v_arg));
  802.                     (void) putc('\n',stderr);
  803.                     break;
  804.           case PUSHD1:    fprintf(stderr," %c dummy\n",
  805.                       arg->udf_arg->udf_name[0]);
  806.                     break;
  807.           case PUSHD2:    fprintf(stderr," %c dummy\n",
  808.                       arg->udf_arg->udf_name[1]);
  809.                     break;
  810.           case CALL:    fprintf(stderr," %s", arg->udf_arg->udf_name);
  811.                     if(level < 6) {
  812.                     if (arg->udf_arg->at) {
  813.                         (void) putc('\n',stderr);
  814.                         disp_at(arg->udf_arg->at,level+2); /* recurse! */
  815.                     } else
  816.                         fputs(" (undefined)\n",stderr);
  817.                     }
  818.                     break;
  819.           case CALL2:    fprintf(stderr," %s", arg->udf_arg->udf_name);
  820.                     if(level < 6) {
  821.                     if (arg->udf_arg->at) {
  822.                         (void) putc('\n',stderr);
  823.                         disp_at(arg->udf_arg->at,level+2); /* recurse! */
  824.                     } else
  825.                         fputs(" (undefined)\n",stderr);
  826.                     }
  827.                     break;
  828.           case JUMP:
  829.           case JUMPZ:
  830.           case JUMPNZ:
  831.           case JTERN:
  832.                     fprintf(stderr," +%d\n",arg->j_arg);
  833.                     break;
  834.           default:
  835.                     (void) putc('\n',stderr);
  836.         }
  837.     }
  838. }
  839.  
  840.  
  841. /* alloc:
  842.  * allocate memory 
  843.  * This is a protected version of malloc. It causes an int_error 
  844.  * if there is not enough memory, but first it tries FreeHelp() 
  845.  * to make some room, and tries again. If message is NULL, we 
  846.  * allow NULL return. Otherwise, we handle the error, using the
  847.  * message to create the int_error string. Note cp/sp_extend uses realloc,
  848.  * so it depends on this using malloc().
  849.  */
  850.  
  851. char *
  852. alloc(size, message)
  853.     unsigned int size;                /* # of bytes */
  854.     char *message;            /* description of what is being allocated */
  855. {
  856.     char *p;                /* the new allocation */
  857.     char errbuf[100];        /* error message string */
  858.  
  859.     p = malloc(size);
  860.     if (p == (char *)NULL) {
  861. #ifndef vms
  862.        FreeHelp();            /* out of memory, try to make some room */
  863. #endif
  864.        
  865.        p = malloc(size);        /* try again */
  866.        if (p == (char *)NULL) {
  867.           /* really out of memory */
  868.           if (message != NULL) {
  869.              (void) sprintf(errbuf, "out of memory for %s", message);
  870.              int_error(errbuf, NO_CARET);
  871.              /* NOTREACHED */
  872.           }
  873.           /* else we return NULL */
  874.        }
  875.     }
  876.  
  877.     return(p);
  878. }
  879.